/*
 * main.cpp - Grupo 5 - Prog. Avanzada 2011
 *
 *  Javier Dominguez - 4.901.161-6
 *  Marcelo Parada - 1.977.094-9
 *  Rodrigo Ruiz - 4.481.611-2
 *  Maximiliano Silvera - 4.106.938-6
 */
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include "dt/UsuarioDT.h"
#include "logica/IRegistroUsuario.h"
#include "util/ControllerFactory.h"
#include "dt/SingleDT.h"
#include "dt/SolistaDT.h"
#include "dt/BandaDT.h"

void cabecera();
void menuPrincipal();
int iniciarCU(int opcion);
int salir();

// CU Solicitados
int registroUsuario();
int compartirTemaSingle();
int compartirPistaAlbum();
int consultarInfoTema();
int eliminarTema();
int etiquetar();
int reproducirTema();
int salir();

// CU Prueba
int mostrarListadoUsuarios();

using namespace std;

int main()
{
	int opcion;

	while(true)
	{
		system("clear");

		menuPrincipal();

		cin >> opcion;

		/*
		 * Se invoca el metodo que corresponda a la opcion seleccionada,
		 * si este retorna 0 entonces se cierra la aplicacion.
		 */
		if(iniciarCU(opcion) == 0)
		{
			return 0;
		}
	}
}

/*
 * Imprie la cabecera de la pantalla
 */
void cabecera()
{
	system("clear");

	cout << "------------------------------------------------------------------------- \n";
	cout << "|         .:: Prog. Avanzada 2011 - Grupo 5 - Tarea 7 ::.               | \n";
	cout << "------------------------------------------------------------------------- \n\n";
}

/*
 * Dibuja el menu principal
 */
void menuPrincipal()
{
	cabecera();

	cout << "1. Registrar de Usuario. \n";
	cout << "2. Compartir Tema Single. \n";
	cout << "3. Compartir Pista Album. \n";
	cout << "4. Consultar Información Tema. \n";
	cout << "5. Eliminar Tema. \n";
	cout << "6. Etiquetar. \n";
	cout << "7. Reproducir Tema. \n";
	cout << "10. Mostrar listado usuarios. \n";
	cout << "0. Salir. \n\n";

	cout << "Indique la opcion deseada: ";
}

/*
 * Inicia el Caso de uso correspondiente de acuerdo a la opcion
 * ingresada por el usuario
 */
int iniciarCU(int opcion)
{
	cabecera();

	if(opcion == 0)
	{
		return salir();
	}
	else if(opcion == 1)
	{
		return registroUsuario();
	}
	else if(opcion == 2)
	{
		return compartirTemaSingle();
	}
	else if(opcion == 3)
	{
		return compartirPistaAlbum();
	}
	else if(opcion == 4)
	{
		return consultarInfoTema();
	}
	else if(opcion == 5)
	{
		return eliminarTema();
	}
	else if(opcion == 6)
	{
		return etiquetar();
	}
	else if(opcion == 7)
	{
		return reproducirTema();
	}
	else if(opcion == 8)
	{
		return mostrarListadoUsuarios();
	}

	return 1;
}

int salir()
{
	cout << "Gracias por todo, presione una tecla para salir.";

	getchar();
	getchar();

	system("clear");

	return 0;
}


/*
 * CU - Registro de Usuario
 *
 * El caso de uso comienza cuando el Usuario desea registrarse en la red.
 * Para ello debe ingresar su nombre completo, mail y el nick que lo identificar� en la red.
 * Si el nick ingresado est� disponible, el Sistema registra el nuevo usuario en la red,
 * de lo contrario el Usuario cambia el nick hasta que est� disponible o decida cancelar el registro.
 */
int registroUsuario()
{
	IRegistroUsuario *controller = ControllerFactory::getInstance()->getRegistroUsuarioController();

	// Solicito los datos del usuario
	string nick;

	string nombre;

	string mail;

	cout << "Ingrese los datos del usuario.\n\n";

	cout << "Nombre: "; cin >> nombre;

	cout << "E-mail: "; cin >> mail;

	// Chequeo si nick esta disponible
	bool nickDisponible = false;

	int opcion;

	while(!nickDisponible)
	{
		cout << "Nick: ";

		cin >> nick;

		nickDisponible = controller->nickDisponible(nick);

		// Si nick no disponible solicito nuevamente el nick o permito cancelar y vuelve al menu
		if(!nickDisponible)
		{
			cout << "Nick no disponible. [1: Reintentar || 0: Cancelar]:";

			cin >> opcion;

			if(opcion != 1)
			{
				return 0;
			}
		}
	}

	// Registro el usuario en la aplicacion
	UsuarioDT *usuarioDT = new UsuarioDT(nick, nombre, mail);

	controller->registrarUsuario(usuarioDT);

	cout << "\nUsuario registrado correctamente.\n";

	getchar();

	getchar();

	// Limpio la memoria
	delete usuarioDT;

	return 1;
}

/*
 * CU - Compartir Tema Single
 *
 * El caso de uso comienza cuando el Usuario desea compartir un nuevo single,
 * ingresando el t�tulo, duraci�n y a�o del mismo. Luego ingresa uno a uno los
 * artistas que interpretan el single (al menos uno). En caso de existir el artista
 * en la red ingresa su nombre, mientras que si es nuevo indica su nombre, si es
 * solista o banda y la cantidad de integrantes (si es banda). Para finalizar, el
 * Sistema da de alta el nuevo tema single as� como los nuevos artistas y devuelve un
 * id generado para identificar al tema en el Sistema.
 */
int compartirTemaSingle()
{
	ICompartirTemaSingle *controller = ControllerFactory::getInstance()->getCompartirTemaSingleController();

	// Solicito informacion de single
	string tituloSingle;

	int minutosSingle;

	int segundosSingle;

	int anioSingle;

	cout << "Ingrese los datos del Single. \n\n";

	cout << "Titulo: "; cin >> tituloSingle;

	cout << "Minutos (dur.): "; cin >> minutosSingle;

	cout << "Segundos (dur.): "; cin >> segundosSingle;

	cout << "A�o: "; cin >> anioSingle;

	Tiempo *duracionSingle = new Tiempo(minutosSingle, segundosSingle);

	SingleDT *singleDT = new SingleDT(anioSingle, tituloSingle, duracionSingle);

	// Solicito los artistas

	cout << "Ingrese los artistas del single. \n\n";

	ColConcrete<ArtistaDT*> *colArtistas = new ColConcrete<ArtistaDT*>();

	string nombreArtista;

	int integrantesArtista;

	int tipoArtista;

	bool agregarOtroArtista;

	int opcion;

	do
	{
		cout << "Nombre artista: "; cin >> nombreArtista;

		// Chequeo si existe el artista
		if(!controller->existeArtista(nombreArtista))
		{
			cout << "El artista no existe, debe completar todos los datos." << endl << endl;

			cout << "Indique el tipo de artista. [1: Solista, 2: Banda]."; cin >> tipoArtista;

			if(tipoArtista == 1)
			{
				colArtistas->add(new SolistaDT(nombreArtista));
			}
			else if(tipoArtista == 2)
			{
				cout << "Cantidad integrantes: "; cin >> integrantesArtista;

				colArtistas->add(new BandaDT(nombreArtista, integrantesArtista));
			}
		}

		cout << "�Desea agregar otro artista?. [1: SI || 0: No]:";

		cin >> opcion;

		if(opcion == 1)
		{
			agregarOtroArtista = true;
		}
		else
		{
			agregarOtroArtista = false;
		}
	}
	while(agregarOtroArtista);

	// Ingreso la informacion al sistema
	controller->registrarSingle(singleDT);

	ConcreteIterator<ArtistaDT*> *iterArtistas = colArtistas->getIterator();

	while(iterArtistas->hasCurrent())
	{
		ArtistaDT *currArtistaDT = iterArtistas->current();

		controller->registrarArtista(currArtistaDT);

		controller->asociarArtistaSingle(currArtistaDT->getNombre(), singleDT->getTitulo());

		iterArtistas->next();

		delete currArtistaDT;
	}

	cout << "\nSingle compartido correctamente.\n";

	getchar();

	getchar();

	// Limpio la memoria
	delete duracionSingle;

	delete singleDT;

	delete colArtistas;

	delete iterArtistas;

	return 1;
}

/*
 * CU - Compartir Pista Album
 *
 * El caso de uso comienza cuando el Usuario desea compartir una nueva pista de �lbum,
 * ingresando el t�tulo, duraci�n y n�mero de pista. Luego ingresa uno a uno los artistas
 * que interpretan la pista (al menos uno). En caso de existir el artista en la red
 * ingresa su nombre, mientras que si es nuevo indica su nombre, si es solista o banda
 * y la cantidad de integrantes (si es banda). Una vez ingresados los artistas, el Sistema
 * lista los �lbumes registrados en la red. El Usuario selecciona uno de ellos o en caso de
 * no estar en el listado lo da de alta ingresando su nombre, a�o de edici�n y artistas que
 * lo interpretan (de igual forma que para artistas de la pista). Para finalizar, el Sistema
 * de alta la nueva pista de �lbum, los nuevos artistas, el �lbum (si aplica) y devuelve un id
 * generado para identificar al tema en el Sistema.
 */
int compartirPistaAlbum()
{
	return 1;
}

/*
 * CU - Consultar Informacion de Tema
 *
 * El caso de uso comienza cuando el Usuario quiere obtener la informaci�n de un tema. Para ello
 * ingresa el id de un tema a consultar y el Sistema muestra toda la informaci�n del tema
 * incluyendo los datos de sus artistas, �lbum (si aplica), cantidad de reproducciones totales
 * y fecha de �ltima reproducci�n
 */
int consultarInfoTema()
{
	return 1;
}

/*
 * CU - Eliminar Tema
 *
 * El caso de uso comienza cuando el Usuario desea quitar un tema de la red. Para ello el
 * Sistema muestra una lista de temas compartidos en la red. El Usuario selecciona de esa
 * lista el id del tema a eliminar y el Sistema lo elimina s�lo en caso de que no haya sido
 * escuchado por ning�n usuario de la red, de lo contrario se genera un error y no se elimina el tema.
 */
int eliminarTema()
{


	return 1;
}

/*
 * CU - Etiquetar
 *
 * El caso de uso comienza cuando el Usuario desea etiquetar un �lbum o artista registrado.
 * Para ello indica el elemento a etiquetar (�lbum o artista) y el Sistema muestra la
 * informaci�n completa de los elementos disponibles en la red de acuerdo a la opci�n
 * ingresada. Luego el Usuario selecciona el elemento a etiquetar de la lista correspondiente
 * y el Sistema muestra sus etiquetas y lista adem�s las disponibles en la red. El Usuario
 * agrega una a una las etiquetas (al menos una) y en caso de querer utilizar etiquetas no
 * registradas, ingresa el nombre de cada nueva etiqueta. Para finalizar, el Sistema muestra
 * la informaci�n del elemento a etiquetar y sus nuevas etiquetas, debiendo el Usuario confirmar
 * o cancelar dicho etiquetado. En caso de confirmar, el Sistema efect�a el etiquetado y da de
 * alta las nuevas etiquetas.
 */
int etiquetar()
{
	return 1;
}

/*
 * CU - Reproducir Tema
 *
 * El caso de uso comienza cuando el Usuario desea escuchar un tema. Para ello puede hacerlo
 * indicando directamente su nick y el id del tema a escuchar o bien buscando por etiquetas.
 * En este �ltimo caso el Sistema muestra un listado de etiquetas registradas, de las cuales
 * el Usuario selecciona una. A partir de esta selecci�n el Sistema muestra los temas de los
 * artistas o �lbumes que contengan esa etiqueta. Para finalizar el Usuario ingresa el id de
 * un tema del listado (y su nick) y el Sistema registra la reproducci�n del tema.
 */
int reproducirTema()
{
	return 1;
}

/**
 * CU de prueba para mostrar el listado de los usuarios ingresados
 */
int mostrarListadoUsuarios()
{
	IRegistroUsuario *controller = ControllerFactory::getInstance()->getRegistroUsuarioController();

	ColConcrete<UsuarioDT*> *listaUsuarios = controller->obtenerListadoUsuarios();

	listaUsuarios->~ColConcrete();

	cout << "Usuarios registrados despues borrar \n" << listaUsuarios->toString();

	return 1;
}
